from django.shortcuts import render,redirect
from django.views import View
from django import http
from django.urls import reverse
import re,json,logging
from django.contrib.auth import login,authenticate,logout
from users.models import User,Address
from django.db import DatabaseError
from ershou_shop.utils.response_code import RETCODE
from users.utils import get_active_url,save_access_token
from django_redis import get_redis_connection
from django.contrib.auth.mixins import LoginRequiredMixin
from ershou_shop.utils.view import LoginRequiredJsonMixin
from celery_tasks.email.tasks import send_verify_email
from goods.models import SKU
# Create your views here.
from carts.utils import merge_carts_cookies_redis

logger = logging.getLogger('django')


class UserBrowseHistory(LoginRequiredJsonMixin,View):
    ''''用户浏览记录'''
    def get(self,request):
        redis_con = get_redis_connection('history')
        user = request.user
        sku_ids = redis_con.lrange('history_%s' % user.id,0,-1)
        skus = []
        for sku_id in sku_ids:
            sku = SKU.objects.get(id = sku_id)
            skus.append({
                'id':sku.id,
                'name':sku.name,
                'price':sku.price,
                'default_image_url':sku.default_image.url
            })
        return http.JsonResponse({'code':'200','errmsg':'OK','skus':skus})

    def post(self,request):
    #接受参数
        json_str = request.body.decode()
        json_dict = json.loads(json_str)
        sku_id = json_dict.get('sku_id')
    #校验参数
        try:
            SKU.objects.get(id = sku_id)
        except SKU.DoesNotExist:
            return  http.HttpResponseForbidden('参素错误')
    #保存sku_id到redis
        redis_con = get_redis_connection('history')
        user = request.user
        pl = redis_con.pipeline()
    #去重
        pl.lrem('history_%s' %user.id,0 , sku_id)
        pl.lpush('history_%s'% user.id,sku_id)
        pl.ltrim('history_%s'% user.id,0,4)
        pl.execute()


    #响应结果
        return http.JsonResponse({'code':'200','errmsg':'OK'})






class UpdateTitleAddressView(LoginRequiredJsonMixin, View):
    """更新地址标题"""

    def put(self, reqeust, address_id):
        """实现更新地址标题逻辑"""
        # 接收参数：title
        json_dict = json.loads(reqeust.body.decode())
        title = json_dict.get('title')

        # 校验参数
        if not title:
            return http.HttpResponseForbidden('缺少title')

        try:
            # 查询当前要更新标题的地址
            address = Address.objects.get(id=address_id)
            # 将新的地址标题覆盖地址标题\
            address.title = title
            address.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '更新标题失败'})

        # 响应结果
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '更新标题成功'})


class DefaultAddressView(LoginRequiredJsonMixin, View):
    """设置默认地址"""

    def put(self, reqeust, address_id):
        """实现设置默认地址逻辑"""
        try:
            # 查询出当前哪个地址会作为登录用户的默认地址
            address = Address.objects.get(id=address_id)

            # 将指定的地址设置为当前登录用户的默认地址
            reqeust.user.default_address = address
            reqeust.user.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '设置默认地址失败'})
        # 响应结果
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '设置默认地址成功'})


class UpdateDestoryAddressView(LoginRequiredJsonMixin, View):
    """更新和删除地址"""

    def put(self, request, address_id):
        """更新地址"""
        # 接收参数
        json_dict = json.loads(request.body.decode())
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')

        # 校验参数
        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return http.HttpResponseForbidden('缺少必传参数')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('参数mobile有误')
        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.HttpResponseForbidden('参数tel有误')
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return http.HttpResponseForbidden('参数email有误')

        # 使用最新的地址信息覆盖指定的旧的地址信息
        try:
            Address.objects.filter(id=address_id).update(
                user=request.user,
                title=receiver,
                receiver=receiver,
                province_id=province_id,
                city_id=city_id,
                district_id=district_id,
                place=place,
                mobile=mobile,
                tel=tel,
                email=email
            )
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '修改地址失败'})

        # 响应新的地址信息给前端渲染
        address = Address.objects.get(id=address_id)
        address_dict = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '修改地址成功', 'address': address_dict})

    def delete(self, request, address_id):
        """删除地址"""
        # 实现指定地址的逻辑删除：is_delete=True
        try:
            address = Address.objects.get(id=address_id)
            address.is_deleted = True
            address.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '删除地址失败'})

        # 响应结果：code, errmsg
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '删除地址成功'})


class AddressCreateView(LoginRequiredJsonMixin, View):
    """新增地址"""

    def post(self, reqeust):
        """实现新增地址逻辑"""

        # 判断用户地址数量是否超过上限：查询当前登录用户的地址数量
        # count = Address.objects.filter(user=reqeust.user).count()
        count = reqeust.user.addresses.count()  # 一查多，使用related_name查询
        if count > 20:
            return http.JsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': '超出用户地址上限'})

        # 接收参数
        json_str = reqeust.body.decode()
        json_dict = json.loads(json_str)
        receiver = json_dict.get('receiver')
        province_id = json_dict.get('province_id')
        city_id = json_dict.get('city_id')
        district_id = json_dict.get('district_id')
        place = json_dict.get('place')
        mobile = json_dict.get('mobile')
        tel = json_dict.get('tel')
        email = json_dict.get('email')

        # 校验参数
        if not all([receiver, province_id, city_id, district_id, place, mobile]):
            return http.HttpResponseForbidden('缺少必传参数')
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return http.HttpResponseForbidden('参数mobile有误')
        if tel:
            if not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):
                return http.HttpResponseForbidden('参数tel有误')
        if email:
            if not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
                return http.HttpResponseForbidden('参数email有误')

        # 保存用户传入的地址信息
        try:
            address = Address.objects.create(
                user=reqeust.user,
                title = receiver, # 标题默认就是收货人
                receiver = receiver,
                province_id = province_id,
                city_id = city_id,
                district_id = district_id,
                place = place,
                mobile = mobile,
                tel = tel,
                email = email,
            )

            # 如果登录用户没有默认的地址，我们需要指定默认地址
            if not reqeust.user.default_address:
                reqeust.user.default_address = address
                reqeust.user.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '新增地址失败'})

        # 构造新增地址字典数据
        address_dict = {
            "id": address.id,
            "title": address.title,
            "receiver": address.receiver,
            "province": address.province.name,
            "city": address.city.name,
            "district": address.district.name,
            "place": address.place,
            "mobile": address.mobile,
            "tel": address.tel,
            "email": address.email
        }

        # 响应新增地址结果：需要将新增的地址返回给前端渲染
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '新增地址成功', 'address': address_dict})


class AddressView(LoginRequiredMixin, View):
    """用户收货地址"""

    def get(self, request):
        """查询并展示用户地址信息"""

        # 获取当前登录用户对象
        login_user = request.user
        print(login_user.default_address_id)
        # 使用当前登录用户和is_deleted=False作为条件查询地址数据
        addresses = Address.objects.filter(user=login_user, is_deleted=False)

        # 将用户地址模型列表转字典列表:因为JsonResponse和Vue.js不认识模型类型，只有Django和Jinja2模板引擎认识
        address_list= []
        for address in addresses:
            address_dict = {
                "id": address.id,
                "title": address.title,
                "receiver": address.receiver,
                "province": address.province.name,
                "city": address.city.name,
                "district": address.district.name,
                "place": address.place,
                "mobile": address.mobile,
                "tel": address.tel,
                "email": address.email
            }
            address_list.append(address_dict)
        print(address_list)
        # 构造上下文
        context = {
            'default_address_id':login_user.default_address_id or '0',
            'addresses': address_list
        }

        return render(request, 'user_center_site.html', context)



class Active_Email(View):
    '''验证邮箱'''
    def get(self,request):
        token = request.GET.get('token')
        data =save_access_token(token)
        user_id = data.get('user_id')
        email = data.get('email')
        print(type(email))
        print(email)
        print(user_id)
        user1 = User.objects.get(id=user_id,email=email)
        print(user_id)
        user1.email_active=True
        user1.save()
        return http.HttpResponse('激活成功')
class EmailView(LoginRequiredJsonMixin,View):
    '''添加邮箱'''
    def put(self,request):
        #获取参数
        json_str = request.body.decode()
        json_dict = json.loads(json_str)
        email = json_dict.get('email')
        print(email)
        #校验参数
        if not re.match(r'^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$',email):
            return http.HttpResponseForbidden('参数错误')
        # 将用户闯入的邮箱保存到数据库的Email的字段中
        try:
            request.user.email = email
            request.user.save()
        except Exception as e:
            logger.error(e)
            return http.JsonResponse({'code':RETCODE.DBERR,'errmsg':'添加邮箱失败'})
        #发送流程
        # get_active_url(request.user)
        send_verify = get_active_url(request.user)
        send_verify_email(email,send_verify)
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'ok'})





class UserCener(LoginRequiredMixin,View):
    '''用户中心'''
    def get(self,request):
        #r如果loginRequiredMixin判断用户已登录，那么reques。user就是登录用户对象
        context = {
            'username':request.user.username,
            'mobile':request.user.mobile,
            "email":request.user.email,
            "email_active":request.user.email_active,
        }




        return render(request, 'user_center.html',context)



class LoginOut(View):
    '''用户推出登录'''
    def get(self,request):
        #清楚状态保持信息
        logout(request)
        #退出登录
        response=redirect(reverse('contents:index'))
        #清楚cookie
        response.delete_cookie('username')
        return response


class Usernamecheck(View):
    '''判断用户名是否重复'''
    def get(self,request,username):
        count=User.objects.filter(username=username).count()
        print(type(count))
        print(count)
        return http.JsonResponse({'code': RETCODE.OK,  'errmsg': 'ok' , 'count' : count})

class RegisterView(View):
    '''用户注册'''

    def get(self,request):
        """提供用户注册页面"""
        return render(request,'register.html',{'error_messge':''})

    def post(self,request):
        """进行用户注册的处理"""
        #1.接收参数
        username = request.POST.get('username')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        mobile = request.POST.get('mobile')
        allow = request.POST.get('allow')
        mobile1=request.POST.get('sms_code')
        #2.校验参数
        # 2.1判断数据是否齐全
        if not all([username,password,password2,mobile,allow]):
            return http.HttpResponseForbidden('大神求放过，小白玩家，请高抬贵手')

        #2.2判断用户名等是否合法，
        if password!=password:
            return render(request, 'register.html', {'error_messge': '两次密码不一致，请从新输如'})
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$',username):
            return http.HttpResponseForbidden('大神求放过，小白玩家，请高抬贵手')
        if not re.match(r'^[0-9A-Za-z]{8,20}$',password):
            return http.HttpResponseForbidden('大神求放过，小白玩家，请高抬贵手')
        if not re.match(r'^1[3-9]\d{9}$',mobile):
            return http.HttpResponseForbidden('大神求放过，小白玩家，请高抬贵手')
        #2.3判断用户名手机号是否重复
        # name = User.objects.get("username")
        # if name == username:
        #     return render(request,'register.html',{'error_messge':'用户名已经被注册'})


        #2.3判断用户是否勾选协议
        if  allow==False:
            return http.HttpResponseForbidden('请勾选协议')
        #判断用户是否输如正确的短信验证码
        re_con = get_redis_connection('image_code')
        mobile_re=re_con.get('sms_%s'%mobile).decode()
        if mobile1 != mobile_re:
            return render(request,'register.html',{'error_messge':'验证码输如错误'})
        #3.保存数据
        try:
            user =User.objects.create_user(username=username,password=password,mobile=mobile)
        except DatabaseError:
            return render(request,'register.html',{'error_messge':'注册失败'})
        login(request,user)
        # 4.返回相应
        return redirect(reverse('contents:index'))


class LoginViev(View):
    '''用户登录'''
    def get(self,request):
        return render(request,'login.html')

    def post(self,request):
        #1.获去参数
        username = request.POST.get('username')
        password = request.POST.get('password')
        remebered =request.POST.get('remembered')
        if not all([username,password]):
            return http.HttpResponseForbidden("缺少参数")
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return http.HttpResponseForbidden('大神求放过，小白玩家，请高抬贵手')
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseForbidden('大神求放过，小白玩家，请高抬贵手')

        user = authenticate(username=username,password=password)
        if user is None:
            return render(request, 'login.html', {'account_errmsg': '没有找到此用户'})

        login(request,user)
        if remebered =='on':
            request.session.set_expiry(120)
        else:
            request.session.set_expiry(0)
        next = request.GET.get('next')
        if next:
            #重定向到
            response = redirect(next)
        else:
            response = redirect(reverse('contents:index'))

        response.set_cookie('username', user.username, max_age=120)

        #合并购物车到redies数据库
        response = merge_carts_cookies_redis(request=request,user=user,response=response)

        return response















